#coding:utf-8
import threading
import traceback
from twisted.internet import reactor
from twisted.python import log
from functools import wraps



def execute(func):
        def wrapper(self,*a,**kw):
                if threading.currentThread() != threading._MainThread():
                        self.statistic["thr"]+=1
                try:
                        func(self,*a,**kw)
                except Exception:
                        self.statistic["err"]+=1
                        log.msg(traceback.format_exc())
        return wrapper
                        
def Bootstrap(xpath):
        def wrapper(func):
                func._bootstrap_func = xpath
                return func
        return wrapper

def Observer(xpath):
        def wrapper(func):
                func._observer_func = xpath
                return func
        return wrapper
        
def MaybeCallInThread(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
                if threading.currentThread() is threading._MainThread():
                        reactor.callInThread(func,*args,**kwargs)
                else:
                        func(*args,**kwargs)
        return wrapper
        
def CallInMainThread(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
                if not threading.currentThread() is threading._MainThread():  
                        reactor.callFromThread(func,*args,**kwargs)
                else:
                        func(*args,**kwargs)
        return wrapper
             
        
def Lock(lockname):
        def locker(func):
                @wraps(func)
                def wrapper(self,*args,**kwargs):
                        with getattr(self,lockname):
                                return func(self,*args,**kwargs)
                return wrapper
        return locker


        
def isState(predicate):
        '''
                декоратор "семафор" проверающий состояние клиента
                для разрешения выполнения функции
        '''
        assert callable(predicate)
        def call(func):
                @wraps(func)
                def wrapper(self,*args,**kwargs):
                        if predicate(self.state):
                                return func(self,*args,**kwargs)
                return wrapper
        return call 
